#include "core/include/types.h"
#include "core/include/aks_processor.h"
#include "core/include/process.h"

#include "include/usb_host.h"
#include "include/usb_tsk.h"
#include "include/usb_kbd.h"
#include "chip/include/sl811hst.h"

PROCESS usb_process =
{
	usb_tsk,
    NULL,
    usb_tsk_wakeUp,
    NULL,
    0
};

LIST_ITEM usbItm
=
{
    NULL,
    &usb_process
};


BOOL USB_device_is_exist;
USB_DEV dev_descriptor;
BYTE USB_device_type;
BYTE deviceStat;

BYTE  SS_idx;
DWORD SL811HST_BASE_ADR;
DWORD SL811HST_ADR;
DWORD SL811HST_DAT;


/* ----------- USB Device Driver ------------- */
typedef void (*USB_INIT_DRIVER)(USB_DEV *);
void dummy_Usb_Init_Driver(USB_DEV *dev)
{
    return;
}

static const USB_INIT_DRIVER USB_deviceInitializer[]
=
{
    USBKBD_init,
    dummy_Usb_Init_Driver
};

/* ------------ USB Device Judge ------------ */
BOOL USB_detectKeyboard(USB_DEV *dev)
{
    if(dev->bClass == 0x3   && dev->bSubClass == 0x1 &&    // HID Boot Device ?
       dev->CFG->bNumIF > 0 && dev->CFG->IF->bNumEP > 0 && //
       dev->CFG->IF->DATA->bDesc == 0x21&&  // HID Device
       dev->CFG->IF->DATA->bType == 0x1     // Keyboard
       )
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}


/* --------------- USB Device Type Detection --------------- */
#define USB_TYPE_KEYBOARD   0
#define USB_INVALID_DEVICE  1 // terminator

#define IS_VALID_USB_DEVICE(x)  (0 <= x && x < USB_INVALID_DEVICE)

BYTE USB_deviceType(USB_DEV *dev)
{
    if(TRUE == USB_detectKeyboard(dev))    return USB_TYPE_KEYBOARD;

    return USB_INVALID_DEVICE;
}

BOOL init_usb_tsk(BYTE SS_index)
{
	deviceStat = 0;
	USB_device_is_exist = FALSE;
	USB_device_type = -1;

	// create base address;
	SL811HST_BASE_ADR = ((DWORD)(SS_index) << 21) & 0xE00000;
	SL811HST_ADR = SL811HST_BASE_ADR + 0;
	SL811HST_DAT = SL811HST_BASE_ADR + 1;

	SS_idx = SS_index;

	SL811_USB_Reset();

	UART_transmitString(UART_DBG, (BYTE *)"init_usb_tsk(): finished\r\n");

	return TRUE;
}

void usb_tsk(void *param)
{
	// Any device was attached
	if(USB_device_is_exist == FALSE && 0!=deviceStat)
	{
		UART_transmitString(UART_DBG, (BYTE *)"Start USB_Enumration ...");
		USB_device_is_exist = USB_Enumration(&dev_descriptor);
		USB_device_type = USB_deviceType(&dev_descriptor);
		UART_transmitString(UART_DBG, (BYTE *)"Finish\r\n");

		// for Debug
		showDevDsc(&dev_descriptor);

		// Install Device task
		if(IS_VALID_USB_DEVICE(USB_device_type))
		{
			USB_deviceInitializer[USB_device_type](&dev_descriptor);

			TIMER_resetCallback(SS_idx, usb_kbd_tsk);

//			entryNewCyclicProcess(&USB_deviceTsk[USB_device_type]);
		}
	}
	// The device was detached
	else if(USB_device_is_exist == TRUE && 0==deviceStat)
	{
		UART_transmitString(UART_DBG, (BYTE *)"Start Uninstall ...");

		deviceStat = 0;
		USB_device_is_exist = FALSE;
		USB_device_type = -1;
		SL811_USB_Reset();

		UART_transmitString(UART_DBG, (BYTE *)"Finish\r\n");
	}

	sleepCurrentProcess(usb_tsk_wakeUp, NULL);

	return;
}


BOOL usb_tsk_wakeUp(void *param)
{
	deviceStat =USB_deviceCheck();

	// Any device was attached
	if(USB_device_is_exist == FALSE && 0!=deviceStat)
	{
		UART_transmitString(UART_DBG, (BYTE *)"Any Device was attached\r\n");
		return TRUE;
	}
	// The device was detached
	else if(USB_device_is_exist == TRUE && 0==deviceStat)
	{
		UART_transmitString(UART_DBG, (BYTE *)"The Device was detached\r\n");
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}
